<?php
require_once dirname(__FILE__) . '/Migrate.abstract.php';
class WFMigrate16to20 extends AMigrate
{
    /**
     *\brief Desciption
     * This method is main() function of Migration WF16 to WF20
     * @see AMigrate::execute()
     */
    public function execute(){
        $strPathPidFile = $this->objWidgetPoolFactory->getWFHome() . '/repository/migrate16to20.pid';
        $objMutex = $this->objWidgetPoolFactory->getIOFactory()->getMutex($strPathPidFile);
        //Step1: Start checking is Migrate WF1.6 to WF2.0 process is mutex!
        if(true === $objMutex->isRunning()){
            $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>Another Update process is running!It is not allowed concurrent Migrate WF1.6 to WF2.0 proccess!';
            throw new WFMigrateMigrateException($msg, WFOpt::UPGRADE_WF_FAILED_IS_NOT_MUTEX);
        }
        $msg = '>>>>Step '.$this->getStepNoAccumulate().': Success checking is Migrate WF1.6 to WF2.0 process is mutex!';
        $this->objLogger->info($msg);
        
        $this->doStepCheckFolderWidgetOldExisted();
        
        $this->doStepCheckWFDB();
        
        $this->doStepInitWFDBSchema();
        
        $this->doStepSynWidgetXMLToDB();
        
        $this->doStepSynServerListType();
        
        $this->migrateData();
        /*
        //Step6 : import tmwf_old.proxylist to tmwf.proxylist
        $sql = "SELECT id,owner,deleted,lastcheck,name,hostinfo FROM proxylist ORDER BY id";
        $arrsDataFrom = $this->objFrameworkFrom->getDataObject()->query($sql, array());
        if(is_array($arrsDataFrom) && $arrsDataFrom){
            foreach($arrsDataFrom as $arrDataFrom){
                $objParameter = $this->objFrameworkTo->getParameter();
                $objParameter->appendFrom('proxylist');
                $objParameter->setAssocData($arrDataFrom);
                $isSuccess = $this->objFrameworkTo->getDataObject()->queryInsertByParameter($objParameter);
                if(false === $isSuccess){
                    $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>Failed to Migrate Table proxylist! DB error:' . $this->objFrameworkTo->getDataObject()->getErrMessage();
                    throw new WFDbDatabaseObjectException($msg, WFOpt::UPGRADE_WF_FAILED_MIGRATE_TABLE_PROXYLIST);
                }
            }
        }
        $msg = '>>>>Step6: Success import tmwf_old.proxylist to tmwf.proxylist';
        $this->objLogger->info($msg);
        //Step7 : import tmwf_old.serverlist to tmwf.serverlist
        $sql = "SELECT id,owner,deleted,lastcheck,name,hostinfo FROM serverlist ORDER BY id";
        $arrsDataFrom = $this->objFrameworkFrom->getDataObject()->query($sql, array());
        ////$this->objFrameworkTo->getLogger()->debug($this->objFrameworkTo->getVarLog($arrsDataFrom));
        if(is_array($arrsDataFrom) && $arrsDataFrom){
            foreach($arrsDataFrom as $arrDataFrom){
                if($arrDataFrom['name'] == 'localhost'){ //escape 'localhost'
                    continue;
                }
                $arrDataFrom = $this->getArrDataServerlist16to20ByArrDataFrom($arrDataFrom);
                $objParameter = $this->objFrameworkTo->getParameter();
                $objParameter->appendFrom('serverlist');
                $objParameter->setAssocData($arrDataFrom);
                $isSuccess = $this->objFrameworkTo->getDataObject()->queryInsertByParameter($objParameter);
                if(false === $isSuccess){
                    $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>Failed to Migrate Table serverlist! DB error:' . $this->objFrameworkTo->getDataObject()->getErrMessage();
                    throw new WFDbDatabaseObjectException($msg, WFOpt::UPGRADE_WF_FAILED_MIGRATE_TABLE_SERVERLIST);
                }
            }
        }
        $msg = '>>>>Step7: Success import tmwf_old.serverlist to tmwf.serverlist';
        $this->objLogger->info($msg);
        //Step8 : import tmwf_old.userdata to tmwf.userdata
        $sql = "SELECT id,uid,wid,modname,data,pid FROM userdata ORDER BY id";
        $arrsDataFrom = $this->objFrameworkFrom->getDataObject()->query($sql, array());
        if(is_array($arrsDataFrom) && $arrsDataFrom){
            foreach($arrsDataFrom as $arrDataFrom){
                $arrDataFrom = $this->getArrDataUserdata16to20ByArrDataFrom($arrDataFrom);
                $objParameter = $this->objFrameworkTo->getParameter();
                $objParameter->appendFrom('userdata');
                $objParameter->setAssocData($arrDataFrom);
                $isSuccess = $this->objFrameworkTo->getDataObject()->queryInsertByParameter($objParameter);
                if(false === $isSuccess){
                    $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>Failed to Migrate Table userdata! DB error:' . $this->objFrameworkTo->getDataObject()->getErrMessage();
                    throw new WFDbDatabaseObjectException($msg, WFOpt::UPGRADE_WF_FAILED_MIGRATE_TABLE_USERDATA);
                }
            }
        }
        $msg = '>>>>Step8: Success import tmwf_old.userdata to tmwf.userdata';
        $this->objLogger->info($msg);
        //Step9 : import tmwf_old.users to tmwf.users
        $sql = "SELECT id,email,pass,data,udata,pdata,lang,theme FROM users ORDER BY id";
        $arrsDataFrom = $this->objFrameworkFrom->getDataObject()->query($sql, array());
        if(is_array($arrsDataFrom) && $arrsDataFrom){
            foreach($arrsDataFrom as $arrDataFrom){
                // Process column udata start
                ／*$arrsUdata = json_decode($arrDataFrom['udata'], true);
                if(is_array($arrsUdata) && $arrsUdata){
                    $arrsUdataTmp = array();
                    foreach($arrsUdata as $arrUdata){
                        $uid = isset($arrDataFrom['id']) ? $arrDataFrom['id'] : null;
                        if(null === $uid){
                            $strMsg = __CLASS__ . '::' . __FUNCTION__ . '()=>users.id is null!';
                            throw new WFMigrateMigrateException($strMsg);
                        }
                        $intPageNumber = isset($arrUdata['page']) ? $arrUdata['page'] : null;
                        if(null === $intPageNumber){
                            $strMsg = __CLASS__ . '::' . __FUNCTION__ . '()=>arrUsersUdata[\'page\'] is null!';
                            throw new WFMigrateMigrateException($strMsg);
                        }
                        $strLayout16 = $this->getLayout16ByUserId($uid, $intPageNumber);
                        $arrUdata = $this->getArrDataUsersUdata16to20ByArrDataUdataFrom($strLayout16, $arrUdata);
                        $arrsUdataTmp[] = $arrUdata;
                    }
                }
                $arrDataFrom['udata'] = json_encode($arrsUdataTmp);
                // Process column udata end
                // Process column pdata start
                $arrsPdata = json_decode($arrDataFrom['pdata'], true);
                if(is_array($arrsPdata) && $arrsPdata){
                    $arrsPdataTmp = array();
                    foreach($arrsPdata as $arrPdata){
                        $arrPdata = $this->getArrDataUsersPdata16to20ByArrDataPdataFrom($arrPdata);
                        $arrsPdataTmp[] = $arrPdata;
                    }
                }
                $arrDataFrom['pdata'] = json_encode($arrsPdataTmp);*／
                $arrDataFrom = $this->getArrDataUsers16to20ByArrDataFrom($arrDataFrom);
                // Process column pdata end
                $objParameter = $this->objFrameworkTo->getParameter();
                $objParameter->appendFrom('users');
                $objParameter->setAssocData($arrDataFrom);
                $isSuccess = $this->objFrameworkTo->getDataObject()->queryInsertByParameter($objParameter);
                if(false === $isSuccess){
                    $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>Failed to Migrate Table users! DB error:' . $this->objFrameworkTo->getDataObject()->getErrMessage();
                    throw new WFDbDatabaseObjectException($msg, WFOpt::UPGRADE_WF_FAILED_MIGRATE_TABLE_USERS);
                }
            }
        }
        $msg = '>>>>Step9: Success import tmwf_old.users to tmwf.users';
        $this->objLogger->info($msg);*/
    }
    /**
     *\brief Desciption
     * This method is Table Userdata Migration WF16 to WF20
     */
    protected function getArrDataUsers16to20ByArrDataFrom($arrDataFrom){
        $arrsUdata = json_decode($arrDataFrom['udata'], true);
        if(is_array($arrsUdata) && $arrsUdata){
            $arrsUdataTmp = array();
            foreach($arrsUdata as $arrUdata){
                $uid = isset($arrDataFrom['id']) ? $arrDataFrom['id'] : null;
                if(null === $uid){
                    $strMsg = __CLASS__ . '::' . __FUNCTION__ . '()=>users.id is null!';
                    throw new WFMigrateMigrateException($strMsg);
                }
                $intPageNumber = isset($arrUdata['page']) ? $arrUdata['page'] : null;
                if(null === $intPageNumber){
                    $strMsg = __CLASS__ . '::' . __FUNCTION__ . '()=>arrUsersUdata[\'page\'] is null!';
                    throw new WFMigrateMigrateException($strMsg);
                }
                $strLayout16 = $this->getLayout16ByUserId($uid, $intPageNumber);
                $arrUdata = $this->getArrDataUsersUdata16to20ByArrDataUdataFrom($strLayout16, $arrUdata);
                $arrsUdataTmp[] = $arrUdata;
            }
        }
        $arrDataFrom['udata'] = json_encode($arrsUdataTmp);
        // Process column udata end
        // Process column pdata start
        $arrsPdata = json_decode($arrDataFrom['pdata'], true);
        if(is_array($arrsPdata) && $arrsPdata){
            $arrsPdataTmp = array();
            foreach($arrsPdata as $arrPdata){
                $arrPdata = $this->getArrDataUsersPdata16to20ByArrDataPdataFrom($arrPdata);
                $arrsPdataTmp[] = $arrPdata;
            }
        }
        $arrDataFrom['pdata'] = json_encode($arrsPdataTmp);
        return $arrDataFrom;
    }
    /**
     *\brief Desciption
     * This method is Table Userdata Migration WF16 to WF20
     */
    protected function getArrDataUserdata16to20ByArrDataFrom($arrDataFrom){
        $arrDataFrom['widget_key'] = '';
        $arrDataFrom['param'] = '';
        return $arrDataFrom;
    }
    /**
     *\brief Desciption
     * This method is Table Users.pdata Migration WF16 to WF20
     */
    protected function getArrDataUsersPdata16to20ByArrDataPdataFrom($arrDataPdataFrom){
        $strLayout = $arrDataPdataFrom['layout'];
        // layout 1.6=>2.0
        $arrDataPdataFrom['layout'] = $this->getLayoutMappingByCondition($strLayout);
        $arrDataPdataFrom['allowConfig'] = $this->objFrameworkTo->getTypeFactory()->getString()->getBooleanString($arrDataPdataFrom['allowConfig']);
        $arrDataPdataFrom['allowClose'] = $this->objFrameworkTo->getTypeFactory()->getString()->getBooleanString($arrDataPdataFrom['allowClose']);
        $arrDataPdataFrom['fixedColumn'] = $this->objFrameworkTo->getTypeFactory()->getString()->getNullString($arrDataPdataFrom['fixedColumn']);
        $arrDataPdataFrom['eventCode'] = $this->objFrameworkTo->getTypeFactory()->getString()->getNullString($arrDataPdataFrom['eventCode']);
        $arrDataPdataFrom['boxWidth'] = '';
        $arrDataPdataFrom['autoFit'] = 0;
        return $arrDataPdataFrom;
    }
    /**
     *\brief Desciption
     * This method will get WF16 layout by userid, pageNumber
     */
    protected function getLayout16ByUserId($intUserId, $intPageNumber){
        $arrsUsersPdata = $this->getArrsUsersPdata16ByUserId($intUserId);
        if(is_array($arrsUsersPdata) && $arrsUsersPdata){
            foreach($arrsUsersPdata as $arrUsersPdata){
                if(isset($arrUsersPdata['pageNumber']) && $arrUsersPdata['pageNumber'] == $intPageNumber){
                    return isset($arrUsersPdata['layout']) ? $arrUsersPdata['layout'] : '';
                }
            }
        }
        return '';
    }
    /**
     *\brief Desciption
     * This method will get WF16 users.pdata and transform to arrsDataPdata by userid
     */
    protected function getArrsUsersPdata16ByUserId($intUserId){
        if(! isset(self::$instance[__FUNCTION__][$intUserId])){
            $sql = "SELECT pdata FROM users WHERE id=:id";
            $sqlvalues = array(':id' => $intUserId);
            $arrsData = $this->objFrameworkFrom->getDataObject()->query($sql, $sqlvalues);
            $ret = array();
            if(isset($arrsData[0]) && $arrsData[0]){
                $jsonPdata = $arrsData[0]['pdata'];
                $ret = json_decode($jsonPdata, true);
            }
            self::$instance[__FUNCTION__][$intUserId] = $ret;
        }
        return self::$instance[__FUNCTION__][$intUserId];
    }
    /**
     *\brief Desciption
     * This method is Table Users.udata Migration WF16 to WF20
     */
    protected function getArrDataUsersUdata16to20ByArrDataUdataFrom($strLayout16, $arrDataUdataFrom){
        $strLayout = $strLayout16;
        $strColumn = $arrDataUdataFrom['column'];
        // order 1.6=>2.0
        $intDataUdataColumnOrderFromTmp = $this->getColumnOrderMappingByCondition($strLayout, $strColumn);
        if(null !== $intDataUdataColumnOrderFromTmp){
            $arrDataUdataFrom['order'] = (int) $intDataUdataColumnOrderFromTmp;
        }
        $intDataUdataColumnFromTmp = $this->getColumnMappingByCondition($strLayout, $strColumn);
        if(null !== $intDataUdataColumnFromTmp){
            $arrDataUdataFrom['column'] = (int) $intDataUdataColumnFromTmp;
        }
        
        unset($arrDataUdataFrom['showMin']);
        unset($arrDataUdataFrom['showClose']);
        unset($arrDataUdataFrom['showSetting']);
        unset($arrDataUdataFrom['showHelp']);
        unset($arrDataUdataFrom['allowDrag']);
        unset($arrDataUdataFrom['UniqueCss']);
        $arrDataUdataFrom['widget_key'] = '';
        return $arrDataUdataFrom;
    }
    /**
     *\brief Desciption
     * This method is Table serverlist Migration WF16 to WF20
     */
    protected function getArrDataServerlist16to20ByArrDataFrom($arrDataFrom){
        if(! isset($arrDataFrom['hostinfo'])){
            $msg = __CLASS__ . '::' . __FUNCTION__ . '()=>$arrDataFrom[\'hostinfo\'] is null!';
            throw new WFDbDatabaseObjectException($msg);
        }
        $arrHostInfo = json_decode($arrDataFrom['hostinfo'], true);
        $arrHostInfo['type'] = 'modTMCSS';
        $arrDataFrom['hostinfo'] = json_encode($arrHostInfo);
        return $arrDataFrom;
    }
    /**
     *\brief Desciption
     * This method is WF16 users.pdata layout mapping to WF20
     */
    protected function getLayoutMappingByCondition($strLayout){
        //format : $arrLayoutMapping['1.6layout'] = '2.0layout';
        $arrLayoutMapping = array();
        $arrLayoutMapping['1-0'] = '1';
        $arrLayoutMapping['2-0'] = '2';
        $arrLayoutMapping['3-0'] = '5';
        $arrLayoutMapping['table_1.html'] = '8';
        $arrLayoutMapping['table_2.html'] = '8';
        $arrLayoutMapping['table_3.html'] = '5';
        $arrLayoutMapping['table_4.html'] = '2';
        $arrLayoutMapping['table_5.html'] = '5';
        $arrLayoutMapping['table_6.html'] = '2';
        $arrLayoutMapping['table_7.html'] = '5';
        $arrLayoutMapping['table_8.html'] = '9';
        $arrLayoutMapping['table_9.html'] = '1';
        $ret = isset($arrLayoutMapping[$strLayout]) ? $arrLayoutMapping[$strLayout] : '';
        return $ret;
    }
    /**
     *\brief Desciption
     * This method is WF16 users.udata column mapping to WF20
     */
    protected function getColumnMappingByCondition($strLayout, $strColumn){
        //format : $arrColumnMapping['1.6layout']['1.6column'] = '2.0column';
        $arrColumnMapping = array();
        $arrColumnMapping['table_3.html']['0'] = '0';
        $arrColumnMapping['table_3.html']['1'] = '1';
        $arrColumnMapping['table_3.html']['2'] = '2';
        $arrColumnMapping['table_3.html']['3'] = '1';
        $arrColumnMapping['table_3.html']['4'] = '2';
        $arrColumnMapping['table_4.html']['0'] = '0';
        $arrColumnMapping['table_4.html']['1'] = '1';
        $arrColumnMapping['table_4.html']['2'] = '0';
        $arrColumnMapping['table_4.html']['3'] = '1';
        $arrColumnMapping['table_5.html']['0'] = '0';
        $arrColumnMapping['table_5.html']['1'] = '1';
        $arrColumnMapping['table_5.html']['2'] = '2';
        $arrColumnMapping['table_5.html']['3'] = '0';
        $arrColumnMapping['table_5.html']['4'] = '1';
        $arrColumnMapping['table_5.html']['5'] = '2';
        $arrColumnMapping['table_6.html']['0'] = '0';
        $arrColumnMapping['table_6.html']['1'] = '1';
        $arrColumnMapping['table_6.html']['2'] = '0';
        $arrColumnMapping['table_6.html']['3'] = '1';
        $arrColumnMapping['table_6.html']['4'] = '0';
        $arrColumnMapping['table_6.html']['5'] = '1';
        $arrColumnMapping['table_6.html']['6'] = '0';
        $arrColumnMapping['table_7.html']['0'] = '0';
        $arrColumnMapping['table_7.html']['1'] = '1';
        $arrColumnMapping['table_7.html']['2'] = '2';
        $arrColumnMapping['table_7.html']['3'] = '0';
        $arrColumnMapping['table_7.html']['4'] = '1';
        $arrColumnMapping['table_7.html']['5'] = '2';
        $arrColumnMapping['table_8.html']['0'] = '0';
        $arrColumnMapping['table_8.html']['1'] = '1';
        $arrColumnMapping['table_8.html']['2'] = '2';
        $arrColumnMapping['table_8.html']['3'] = '3';
        $arrColumnMapping['table_8.html']['4'] = '4';
        $arrColumnMapping['table_8.html']['5'] = '3';
        $arrColumnMapping['table_8.html']['6'] = '4';
        $arrColumnMapping['table_8.html']['7'] = '3';
        $ret = isset($arrColumnMapping[$strLayout][$strColumn]) ? $arrColumnMapping[$strLayout][$strColumn] : null;
        return $ret;
    }
    /**
     *\brief Desciption
     * This method is WF16 users.udata column order mapping to WF20
     */
    protected function getColumnOrderMappingByCondition($strLayout, $strColumn){
        //format : $arrColumnOrderMapping['1.6layout']['1.6column'] = '2.0order';
        $arrColumnOrderMapping = array();
        $arrColumnOrderMapping['table_1.html']['0'] = '1';
        $arrColumnOrderMapping['table_1.html']['1'] = '1';
        $arrColumnOrderMapping['table_1.html']['2'] = '1';
        $arrColumnOrderMapping['table_1.html']['3'] = '1';
        $arrColumnOrderMapping['table_1.html']['4'] = '1';
        $arrColumnOrderMapping['table_2.html']['0'] = '1';
        $arrColumnOrderMapping['table_2.html']['1'] = '1';
        $arrColumnOrderMapping['table_2.html']['2'] = '1';
        $arrColumnOrderMapping['table_2.html']['3'] = '1';
        $arrColumnOrderMapping['table_2.html']['4'] = '1';
        $arrColumnOrderMapping['table_3.html']['0'] = '1';
        $arrColumnOrderMapping['table_3.html']['1'] = '1';
        $arrColumnOrderMapping['table_3.html']['2'] = '1';
        $arrColumnOrderMapping['table_3.html']['3'] = '2';
        $arrColumnOrderMapping['table_3.html']['4'] = '2';
        $arrColumnOrderMapping['table_4.html']['0'] = '1';
        $arrColumnOrderMapping['table_4.html']['1'] = '1';
        $arrColumnOrderMapping['table_4.html']['2'] = '2';
        $arrColumnOrderMapping['table_4.html']['3'] = '2';
        $arrColumnOrderMapping['table_5.html']['0'] = '1';
        $arrColumnOrderMapping['table_5.html']['1'] = '1';
        $arrColumnOrderMapping['table_5.html']['2'] = '1';
        $arrColumnOrderMapping['table_5.html']['3'] = '2';
        $arrColumnOrderMapping['table_5.html']['4'] = '2';
        $arrColumnOrderMapping['table_5.html']['5'] = '2';
        $arrColumnOrderMapping['table_6.html']['0'] = '1';
        $arrColumnOrderMapping['table_6.html']['1'] = '1';
        $arrColumnOrderMapping['table_6.html']['2'] = '2';
        $arrColumnOrderMapping['table_6.html']['3'] = '2';
        $arrColumnOrderMapping['table_6.html']['4'] = '3';
        $arrColumnOrderMapping['table_6.html']['5'] = '3';
        $arrColumnOrderMapping['table_6.html']['6'] = '4';
        $arrColumnOrderMapping['table_7.html']['0'] = '1';
        $arrColumnOrderMapping['table_7.html']['1'] = '1';
        $arrColumnOrderMapping['table_7.html']['2'] = '1';
        $arrColumnOrderMapping['table_7.html']['3'] = '2';
        $arrColumnOrderMapping['table_7.html']['4'] = '2';
        $arrColumnOrderMapping['table_7.html']['5'] = '2';
        $arrColumnOrderMapping['table_8.html']['0'] = '1';
        $arrColumnOrderMapping['table_8.html']['1'] = '1';
        $arrColumnOrderMapping['table_8.html']['2'] = '1';
        $arrColumnOrderMapping['table_8.html']['3'] = '1';
        $arrColumnOrderMapping['table_8.html']['4'] = '1';
        $arrColumnOrderMapping['table_8.html']['5'] = '2';
        $arrColumnOrderMapping['table_8.html']['6'] = '2';
        $arrColumnOrderMapping['table_8.html']['7'] = '3';
        $ret = isset($arrColumnOrderMapping[$strLayout][$strColumn]) ? $arrColumnOrderMapping[$strLayout][$strColumn] : null;
        return $ret;
    }
    /*protected function getArrsObjDataMigrate(){
        if(!isset(self::$instance[__FUNCTION__.'16to20'])){
            $ret = array();
            $ret[] = new WFDataMigrate('users', 'id', 'getArrDataUsers16to20ByArrDataFrom');
            $ret[] = new WFDataMigrate('userdata', 'id', 'getArrDataUserdata16to20ByArrDataFrom');
            $objDataMigration = new WFDataMigrate('serverlist', 'id', 'getArrDataServerlist16to20ByArrDataFrom');
            $objDataMigration->setAssocSkipRecordColNameWithColValue('name', 'localhost');
            $ret[] = $objDataMigration;
            $ret[] = new WFDataMigrate('proxylist', 'id');
            self::$instance[__FUNCTION__.'16to20'] = $ret;
        }
        return self::$instance[__FUNCTION__.'16to20'];
    }*/
    protected function initColDataMigrate(){
        $this->colDataMigrate->set('users', new WFDataMigrate('users', 'id', 'getArrDataUsers16to20ByArrDataFrom'));
        $this->colDataMigrate->set('userdata', new WFDataMigrate('userdata', 'id', 'getArrDataUserdata16to20ByArrDataFrom'));
        
        $objDataMigration = new WFDataMigrate('serverlist', 'id', 'getArrDataServerlist16to20ByArrDataFrom');
        $objDataMigration->setAssocSkipRecordColNameWithColValue('name', 'localhost');
        $this->colDataMigrate->set('serverlist', $objDataMigration);
        
        $this->colDataMigrate->set('proxylist',new WFDataMigrate('proxylist', 'id'));
    }
}